package gold.digger;

/**
 * Created by fanzhenyu02 on 2020/6/27.
 * common problem solver template.
 */
public class LC289 {
    public long startExecuteTime = System.currentTimeMillis();


    public void gameOfLife(int[][] board) {
        if (null == board || board.length <= 0) {
            return;
        }

        int m = board.length, n = board[0].length;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == 1) {
                    //live cell die
                    if (liveCellDie(board, i, j)) {
                        board[i][j] = 2; //live->die : 1->2;
                    }
                } else {
                    //dead cell back.
                    if (deadCellBack(board, i, j)) {
                        board[i][j] = 3; //live->die : 0->3;
                    }
                }
            }
        }

        // reset cell back
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == 3) board[i][j] = 1;
                if (board[i][j] == 2) board[i][j] = 0;
            }
        }

        return;
    }

    // Any live cell with fewer than two live neighbors dies, as if caused by under-
//population.
// Any live cell with two or three live neighbors lives on to the next generatio
//n.
// Any live cell with more than three live neighbors dies, as if by over-populat
//ion..
// Any dead cell with exactly three live neighbors becomes a live cell, as if by
// reproduction.

    public boolean liveCellDie(int[][] board, int i, int j) {
        int liveCount = getLiveCount(board, i, j);
        return liveCount < 2 || liveCount > 3;
    }

    public boolean deadCellBack(int[][] board, int i, int j) {
        int liveCount = getLiveCount(board, i, j);
        return liveCount == 3;
    }

    public int getLiveCount(int[][] board, int i, int j) {
        int liveCount = 0;
        int[] deviation = {-1, 0, 1};
        int nextX, nextY;
        for (int k = 0; k < 3; k++) {
            for (int l = 0; l < 3; l++) {
                if (deviation[k] == 0 && deviation[l] == 0) {
                    continue;
                }
                nextX = i + deviation[k];
                nextY = j + deviation[l];
                if (isValidPos(board, nextX, nextY) && (board[nextX][nextY] == 1 || board[nextX][nextY] == 2)) {
                    ++liveCount;
                }
            }
        }

        return liveCount;
    }

    public boolean isValidPos(int[][] board, int i, int j) {
        return i >= 0 && i < board.length && j >= 0 && j < board[0].length;
    }


    //    [
//  [0,1,0],
//  [0,0,1],
//  [1,1,1],
//  [0,0,0]
//]
//Output:
//[
//  [0,0,0],
//  [1,0,1],
//  [0,1,1],
//  [0,1,0]
//]
    public static void main(String[] args) {
        LC289 an = new LC289();
//        int[][] board = InputUtil.toDoubleIntegerArray(" [\n" +
//                "  [0,1,0],\n" +
//                "  [0,0,1],\n" +
//                "  [1,1,1],\n" +
//                "  [0,0,0]\n" +
//                "]");

        int[][] board = {{1}};

        an.gameOfLife(board);

        System.out.println("\nanswer total execute time: " + (System.currentTimeMillis() - an.startExecuteTime) + " ms.");
    }
}
